﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows;

namespace TestUSB
{
    class UsbDevice
    {
        // HID Constants returned by the DLL function calls
        
        // Function returned successfully.
        const byte HID_DEVICE_SUCCESS = 0x00;
        // Indicates that the specified device index was invalid or the device does not exist or is inaccessible.
        const byte HID_DEVICE_NOT_FOUND = 0x01;
        // Indicates that the device must be opened prior to calling the function.
        const byte HID_DEVICE_NOT_OPENED = 0x02; 
        // Indicates that the device is already opened and cannot be re-opened.
        const byte HID_DEVICE_ALREADY_OPENED = 0x03;
        // Indicates that a get or set report function returned due to a timeout. HidDevice_GetInputReport_Interrupt() returned with less bytes than requested.
        const byte HID_DEVICE_TRANSFER_TIMEOUT = 0x04; 
        // The host failed to communicate with the device or function parameters are incorrect.
        const byte HID_DEVICE_TRANSFER_FAILED = 0x05; 
        // Cannot retrieve device path or hidStringType is invalid.
        const byte HID_DEVICE_CANNOT_GET_HID_INFO = 0x06;
        // HID ::CreateFile() handle is invalid.
        const byte HID_DEVICE_HANDLE_ERROR = 0x07;
        // Specified buffer is not large enough to return requested data.
        const byte HID_DEVICE_INVALID_BUFFER_SIZE = 0x08;
        // Indicates that a system error occurred. Call Get-LastError() to retrieve the system error code.
        const byte HID_DEVICE_SYSTEM_CODE = 0x09;
        // The function is only supported on certain Windows versions.
        const byte HID_DEVICE_UNSUPPORTED_FUNCTION = 0x0A;
        // This is the default return code value. This value should never be returned.
        const byte HID_DEVICE_UNKNOWN_ERROR = 0xFF;

        // Variables for enumerating and connecting to correct device

        // Should always be 1 when the device is connected
        uint numDevices;
        // Index of device to connect to (0 to numDevices-1)
        uint deviceNum = 0;
        // Hand to connect to device
        IntPtr handle;
        // Vid & Pid of target device
        ushort vid = 4292; // May be "0x10C4"
        ushort pid = 0256; // Similarly, "0x0100"

        uint bytesRead;

        // default constructor
        public UsbDevice()
        {
            
        }

        // return the number of devices connected matching the vid/pid
        public uint getDevices()
        {
            numDevices = HidDevice_GetNumHidDevices(vid, pid);
            return numDevices;
        }

        // connect to the device matching the vid/pid and index
        public byte openDevice()
        {
            return HidDevice_Open(ref handle, deviceNum, vid, pid, 0);
        }

        // sends the buffer to the device over control endpoint
        public byte sendControl(byte[] buffer)
        {
            return HidDevice_SetOutputReport_Control(handle, buffer, Convert.ToUInt32(buffer.Length));
        }

        // sends the buffer to the device over interrupt endpoint
        public byte sendInterrupt(byte[] buffer)
        {
            return HidDevice_SetOutputReport_Interrupt(handle, buffer, Convert.ToUInt32(buffer.Length));
        }

        // close the connection to the device
        public byte close()
        {
            return HidDevice_Close(handle);
        }

        public byte getInterrupt(byte[] buffer)
        {
            return HidDevice_GetInputReport_Interrupt(handle, buffer, Convert.ToUInt32(buffer.Length), 1, ref bytesRead);
        }

        public byte getControl(byte[] buffer)
        {
            return HidDevice_GetInputReport_Control(handle, buffer, Convert.ToUInt32(buffer.Length));
        }

        public ushort getMaxInput()
        {
            return HidDevice_GetInputReportBufferLength(handle);
        }

        // Imported DLL methods

        // Returns the number of connected devices for a given VID & PID combination
        [DllImport("SLABHIDDevice.dll")]
        public static extern uint HidDevice_GetNumHidDevices(ushort vid, ushort pid);

        // Opens a connection to a connected device using an index returned by HidDevice_GetNumHidDevices
        [DllImport("SLABHIDDevice.dll")]
        public static extern byte HidDevice_Open(ref IntPtr device, uint deviceIndex, ushort vid, ushort pid, uint numInputBuffers);

        // Sends an output report using the control endpoint
        [DllImport("SLABHIDDevice.dll")]
        public static extern byte HidDevice_SetOutputReport_Control(IntPtr device, byte[] buffer, uint bufferSize);

        // Sends an output report using the interrupt endpoint
        [DllImport("SLABHIDDevice.dll")]
        public static extern byte HidDevice_SetOutputReport_Interrupt(IntPtr device, byte[] buffer, uint bufferSize);

        // Closes a connection with a connected device
        [DllImport("SLABHIDDevice.dll")]
        public static extern byte HidDevice_Close(IntPtr device);

        [DllImport("SLABHIDDevice.dll")]
        public static extern byte HidDevice_GetInputReport_Control(IntPtr device, byte[] buffer, uint bufferSize);

        [DllImport("SLABHIDDevice.dll")]
        public static extern byte HidDevice_GetInputReport_Interrupt(IntPtr device, byte[] buffer, uint bufferSize, uint numReports, ref uint bytesReturned);

        [DllImport("SLABHIDDevice.dll")]
        public static extern ushort HidDevice_GetInputReportBufferLength(IntPtr device);
    }
}
